package com.dycong.common.common;

import org.apache.log4j.Logger;

import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * Created by dycong on 2016/12/26.
 */
public class ByteArrayUtil {
    private static Logger logger = Logger.getLogger(ByteArrayUtil.class);

    public ByteArrayUtil() {
    }

    public static void main(String[] args) {
        String string = "i love the A3 girl";
        System.out.println(toHexString(string.getBytes()));
        byte[] bytes = hexStringToByteArray(toHexString(string.getBytes()));
        Byte[] bytes1 = toObject(string.getBytes());
//        print(bytes1,bytes);
        System.out.println(toBase64(string.getBytes()));
        byte[] bytes2 = toSha1(string.getBytes());
        System.out.println(toHexString(bytes2));
    }

    public static void print(Byte[] bytes1) {
        Arrays.stream(bytes1).forEach(o -> System.out.print(o));
//        Arrays.stream(bytes).forEach(o-> System.out.println(o));
    }

    public String bytesToString(byte[] bytes) {
        int count = bytes.length;
        char value[] = new char[count];
        for (int i = count; i-- > 0; ) {
            value[i] = (char) (bytes[i]);
        }
        return value.toString();
    }

    /**
     * @see 每个字节8位ascii码，分别取高四位底四位(通过移位>>与与运算&1111),将每一个单字节char拆分为两个十六进制数
     * hexCode = "0123456789ABCDEF".toCharArray()
     * r.append(hexCode[(b >> 4) & 0xF]);
     * r.append(hexCode[(b & 0xF)]);
     */
    public static String toHexString(byte[] bytes) {
        return DatatypeConverter.printHexBinary(bytes).toUpperCase();
    }

    /**
     * @see 将转化为十六进制的字符串转为byte数组
     */
    public static byte[] hexStringToByteArray(String hex) {
        return DatatypeConverter.parseHexBinary(hex);
    }

    public static String readString(byte[] bytes, Integer offset, Integer length, String... encoding) {
        byte[] toRead = copy(bytes, offset.intValue(), length.intValue());
        if (encoding != null && encoding.length != 0) {
            try {
                return new String(toRead, encoding[0]);
            } catch (UnsupportedEncodingException var6) {
                throw new RuntimeException(var6);
            }
        } else {
            return new String(toRead);
        }
    }

    public static Optional<Date> readDate(byte[] source, int offset, int length, String dateFormatString) {
        /*只执行了readString()方法的copy()操作*/
        String dateStr = readString(source, Integer.valueOf(offset), Integer.valueOf(length), new String[0]);
        return DateUtil.parse(dateStr, dateFormatString);
    }

    public static byte[] copy(byte[] source, int offset, int length) {
        if (offset >= source.length) {
            throw new IllegalArgumentException("offset out of range. offset:" + offset + ", source length" + source.length);
        } else {
            int to = Math.min(source.length, offset + length);
            return Arrays.copyOfRange(source, offset, to);
        }
    }

    /**
     * @param bytes
     * @return
     * @see 装箱
     */
    public static Byte[] toObject(byte[] bytes) {
        Byte[] result = new Byte[bytes.length];

        for (int i = 0; i < bytes.length; ++i) {
            result[i] = Byte.valueOf(bytes[i]);
        }

        return result;
    }

    public static List<Byte> toList(byte[] bytes) {
        return Arrays.asList(toObject(bytes));
    }

    /**
     * @see Base64是一种基于64个可打印字符来表示二进制数据的表示方法.由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。
     */
    public static String toBase64(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] fromBase64(String base64) {
        return Base64.getDecoder().decode(base64);
    }

    /**
     * 返回数组size为20!!!，MD5是生成16位数组
     * @param source
     * @return
     */
    public static byte[] toSha1(byte[] source) {
        MessageDigest crypt = null;

        try {
            crypt = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException var3) {
            throw new RuntimeException(var3);
        }

        crypt.reset();
        crypt.update(source);
        return crypt.digest();
    }
}
